import psutil
import numpy as np
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QSizePolicy, QApplication
from PyQt6.QtCore import QTimer, Qt
from PyQt6.QtGui import QFont, QColor

# PyQt-Fluent-Widgets 导入
from qfluentwidgets import (
    ScrollArea, ComboBox, ProgressBar, CardWidget,
    BodyLabel, SubtitleLabel, CaptionLabel, StrongBodyLabel,
    FluentIcon, InfoBar, InfoBarPosition, setTheme, Theme,
    isDarkTheme, FluentThemeColor, qconfig, TitleLabel
)

from window.resource_monitor.widgets.circular_progress import CircularProgress
from common.widgets.info_card import InfoCard
from window.resource_monitor.widgets.echarts_widget import EChartsWidget
import json
import time


class ResourceMonitor(QWidget):
    def __init__(self):
        super().__init__()
        self.last_network_io = None
        self.disk_usage_cache = {}  # 缓存磁盘使用率，避免不必要的更新
        self.last_disk_io = None  # 缓存磁盘 I/O 数据
        self.init_ui()
        self.setup_monitoring()
        self.update_data()

    def init_ui(self):
        # 设置 Fluent Design 主题
        setTheme(Theme.LIGHT)

        # 设置全局字体大小
        font = QFont()
        font.setPointSize(11)
        font.setFamily("Microsoft YaHei")
        self.setFont(font)

        # 主布局容器
        main_layout = QVBoxLayout(self)
        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.setSpacing(0)

        # 创建滚动区域
        self.scroll_area = ScrollArea()
        self.scroll_area.setWidgetResizable(True)
        self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)

        # 内容容器
        content_widget = QWidget()
        content_widget.setMinimumWidth(800)
        layout = QVBoxLayout(content_widget)
        layout.setSpacing(20)
        layout.setContentsMargins(30, 30, 30, 30)

        # 标题区域
        title_layout = QHBoxLayout()
        title = TitleLabel("资源监控")
        title_layout.addWidget(title)
        title_layout.addStretch()
        layout.addLayout(title_layout)

        # 仪表盘区域
        dashboard_card = self.create_dashboard_card()
        layout.addWidget(dashboard_card)

        # 图表和控制区域
        chart_card = self.create_chart_card()
        layout.addWidget(chart_card)

        # 信息卡片区域
        info_cards = self.create_info_cards()
        layout.addWidget(info_cards)

        # 磁盘分区信息
        disk_card = self.create_disk_card()
        layout.addWidget(disk_card)

        layout.addStretch()

        # 设置滚动区域
        self.scroll_area.setWidget(content_widget)
        main_layout.addWidget(self.scroll_area)

    def create_dashboard_card(self):
        """创建仪表盘卡片"""
        dashboard_card = CardWidget()
        dashboard_card.setFixedHeight(280)

        card_layout = QVBoxLayout(dashboard_card)
        card_layout.setContentsMargins(20, 20, 20, 20)
        card_layout.setSpacing(15)

        # 卡片标题
        title = StrongBodyLabel("系统仪表盘")
        title.setFont(QFont("Microsoft YaHei", 14))
        card_layout.addWidget(title)

        # 仪表盘内容
        dashboard_layout = QHBoxLayout()
        dashboard_layout.setSpacing(30)
        dashboard_layout.setAlignment(Qt.AlignmentFlag.AlignCenter)

        self.cpu_progress = CircularProgress(0, 100, "CPU 使用率", "#0078D7")
        self.memory_progress = CircularProgress(0, 100, "内存使用率", "#4CAF50")
        self.swap_progress = CircularProgress(0, 100, "交换内存使用率", "#FF5722")
        self.disk_progress = CircularProgress(0, 100, "系统盘使用率", "#FF9800")

        dashboard_layout.addWidget(self.cpu_progress, alignment=Qt.AlignmentFlag.AlignCenter)
        dashboard_layout.addWidget(self.memory_progress, alignment=Qt.AlignmentFlag.AlignCenter)
        dashboard_layout.addWidget(self.swap_progress, alignment=Qt.AlignmentFlag.AlignCenter)
        dashboard_layout.addWidget(self.disk_progress, alignment=Qt.AlignmentFlag.AlignCenter)

        card_layout.addLayout(dashboard_layout)

        return dashboard_card

    def create_chart_card(self):
        """创建图表卡片"""
        chart_card = CardWidget()

        card_layout = QVBoxLayout(chart_card)
        card_layout.setContentsMargins(20, 20, 20, 20)
        card_layout.setSpacing(15)

        # 卡片标题
        title = StrongBodyLabel("实时监控图表")
        title.setFont(QFont("Microsoft YaHei", 14))
        card_layout.addWidget(title)

        # ECharts图表
        self.chart = EChartsWidget()
        card_layout.addWidget(self.chart)

        # 控制区域
        control_layout = QHBoxLayout()
        control_layout.setContentsMargins(0, 10, 0, 0)
        control_layout.setSpacing(15)

        # 刷新频率标签
        refresh_label = BodyLabel("⚡ 刷新频率")
        refresh_label.setFont(QFont("Microsoft YaHei", 12))

        # 刷新频率下拉框
        self.refresh_combo = ComboBox()
        self.refresh_combo.addItems(["1秒", "2秒", "5秒", "10秒"])
        self.refresh_combo.setCurrentIndex(0)
        self.refresh_combo.currentIndexChanged.connect(self.change_refresh_rate)
        self.refresh_combo.setFixedWidth(120)

        control_layout.addWidget(refresh_label)
        control_layout.addWidget(self.refresh_combo)
        control_layout.addStretch()

        card_layout.addLayout(control_layout)

        return chart_card

    def create_info_cards(self):
        """创建信息卡片"""
        cards_container = CardWidget()

        container_layout = QVBoxLayout(cards_container)
        container_layout.setContentsMargins(20, 20, 20, 20)
        container_layout.setSpacing(15)

        # 卡片标题
        title = StrongBodyLabel("系统信息")
        title.setFont(QFont("Microsoft YaHei", 14))
        container_layout.addWidget(title)

        # 信息卡片网格
        cards_layout = QGridLayout()
        cards_layout.setSpacing(20)
        cards_layout.setContentsMargins(0, 0, 0, 0)

        self.cpu_logical_cores_card = InfoCard("CPU 逻辑核心", str(psutil.cpu_count(logical=True)), "个", "🧠", "#0078D7")
        self.cpu_physical_cores_card = InfoCard("CPU 物理核心", str(psutil.cpu_count(logical=False)), "个", "💪", "#0078D7")
        self.memory_total_card = InfoCard("总内存", "0", "GB", "💾", "#4CAF50")
        self.memory_available_card = InfoCard("可用内存", "0", "GB", "🆓", "#4CAF50")
        self.network_upload_card = InfoCard("上传速率", "0", "KB/s", "⬆️", "#2196F3")
        self.network_download_card = InfoCard("下载速率", "0", "KB/s", "⬇️", "#2196F3")

        cards_layout.addWidget(self.cpu_logical_cores_card, 0, 0)
        cards_layout.addWidget(self.cpu_physical_cores_card, 0, 1)
        cards_layout.addWidget(self.memory_total_card, 0, 2)
        cards_layout.addWidget(self.memory_available_card, 1, 0)
        cards_layout.addWidget(self.network_upload_card, 1, 1)
        cards_layout.addWidget(self.network_download_card, 1, 2)

        container_layout.addLayout(cards_layout)

        return cards_container

    def create_disk_card(self):
        """创建磁盘信息卡片"""
        disk_card = CardWidget()

        card_layout = QVBoxLayout(disk_card)
        card_layout.setContentsMargins(20, 20, 20, 20)
        card_layout.setSpacing(15)

        # 卡片标题
        title = StrongBodyLabel("磁盘分区信息")
        title.setFont(QFont("Microsoft YaHei", 14))  # 增大字体
        card_layout.addWidget(title)

        # 磁盘信息布局
        self.disk_info_layout = QVBoxLayout()
        self.disk_info_layout.setSpacing(12)
        card_layout.addLayout(self.disk_info_layout)

        self.update_disk_info()

        return disk_card

    def update_disk_info(self):
        """更新磁盘信息 - 优化版本，避免不必要的闪烁"""
        partitions = psutil.disk_partitions(all=False)
        if not partitions:
            # 如果没有磁盘分区，清空布局并显示提示
            for i in reversed(range(self.disk_info_layout.count())):
                widget = self.disk_info_layout.itemAt(i).widget()
                if widget:
                    widget.setParent(None)
                    widget.deleteLater()

            no_disk_label = BodyLabel("未检测到磁盘分区")
            no_disk_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
            self.disk_info_layout.addWidget(no_disk_label)
            return

        # 获取当前磁盘使用情况
        current_disk_usage = {}
        for partition in partitions:
            try:
                if 'cdrom' in partition.opts or 'removable' in partition.opts:
                    continue

                disk_usage = psutil.disk_usage(partition.mountpoint)
                if disk_usage.total == 0:
                    continue

                current_disk_usage[partition.device] = {
                    'percent': disk_usage.percent,
                    'total': disk_usage.total,
                    'used': disk_usage.used,
                    'free': disk_usage.free,
                    'mountpoint': partition.mountpoint
                }
            except Exception as e:
                print(f"获取磁盘信息失败: {partition.mountpoint}, 错误: {e}")
                continue

        # 检查是否需要重建界面（磁盘数量变化或首次运行）
        need_rebuild = (len(current_disk_usage) != len(self.disk_usage_cache) or
                        set(current_disk_usage.keys()) != set(self.disk_usage_cache.keys()) or
                        self.disk_info_layout.count() == 0)

        if need_rebuild:
            # 重建磁盘信息界面
            self.rebuild_disk_info(current_disk_usage)
        else:
            # 只更新变化的进度条和文本
            self.update_existing_disk_info(current_disk_usage)

        # 更新缓存
        self.disk_usage_cache = current_disk_usage.copy()

    def rebuild_disk_info(self, disk_usage_dict):
        """重建磁盘信息界面"""
        # 清除现有组件
        for i in reversed(range(self.disk_info_layout.count())):
            widget = self.disk_info_layout.itemAt(i).widget()
            if widget:
                widget.setParent(None)
                widget.deleteLater()

        # 存储新创建的进度条引用
        self.disk_progress_bars = {}
        self.disk_info_labels = {}

        sorted_devices = sorted(disk_usage_dict.keys())

        for i, device in enumerate(sorted_devices):
            usage_info = disk_usage_dict[device]

            # 磁盘信息容器
            disk_row = QWidget()
            row_layout = QVBoxLayout(disk_row)
            row_layout.setContentsMargins(0, 8, 0, 8)
            row_layout.setSpacing(8)

            # 磁盘名称和使用率信息行
            info_layout = QHBoxLayout()
            info_layout.setContentsMargins(0, 0, 0, 0)
            info_layout.setSpacing(15)

            # 磁盘名称
            name_label = StrongBodyLabel(f"🗄️ {device.replace(':\\', '盘')}")
            name_label.setFont(QFont("Microsoft YaHei", 12))  # 增大字体
            name_label.setFixedWidth(120)

            # 使用情况文字信息
            total_gb = usage_info['total'] / (1024 ** 3)
            used_gb = usage_info['used'] / (1024 ** 3)
            free_gb = usage_info['free'] / (1024 ** 3)

            usage_label = CaptionLabel(f"已用 {used_gb:.1f}GB / 总计 {total_gb:.1f}GB")
            usage_label.setFont(QFont("Microsoft YaHei", 11))  # 增大字体

            free_label = CaptionLabel(f"剩余 {free_gb:.1f}GB ({100 - usage_info['percent']:.1f}%)")
            free_label.setFont(QFont("Microsoft YaHei", 11))  # 增大字体

            info_layout.addWidget(name_label)
            info_layout.addWidget(usage_label)
            info_layout.addStretch()
            info_layout.addWidget(free_label)

            # 进度条
            progress_bar = ProgressBar()
            progress_bar.setValue(int(usage_info['percent']))  # 直接设置当前值，不从0开始
            progress_bar.setFixedHeight(10)  # 稍微增大进度条高度

            row_layout.addLayout(info_layout)
            row_layout.addWidget(progress_bar)

            # 保存引用以便后续更新
            self.disk_progress_bars[device] = progress_bar
            self.disk_info_labels[device] = {
                'usage': usage_label,
                'free': free_label
            }

            # 添加分隔线（除了最后一个）
            if i < len(sorted_devices) - 1:
                separator = QWidget()
                separator.setFixedHeight(1)
                separator.setStyleSheet("background-color: rgba(0, 0, 0, 0.1);")
                row_layout.addWidget(separator)

            self.disk_info_layout.addWidget(disk_row)

    def update_existing_disk_info(self, current_disk_usage):
        """更新现有的磁盘信息，只在数值变化时更新"""
        for device, current_info in current_disk_usage.items():
            if device in self.disk_usage_cache:
                cached_info = self.disk_usage_cache[device]

                # 检查使用率是否有显著变化（大于0.1%）
                if abs(current_info['percent'] - cached_info['percent']) > 0.1:
                    if device in self.disk_progress_bars:
                        self.disk_progress_bars[device].setValue(int(current_info['percent']))

                # 检查容量信息是否变化
                if (current_info['used'] != cached_info['used'] or
                        current_info['free'] != cached_info['free']):
                    if device in self.disk_info_labels:
                        total_gb = current_info['total'] / (1024 ** 3)
                        used_gb = current_info['used'] / (1024 ** 3)
                        free_gb = current_info['free'] / (1024 ** 3)

                        self.disk_info_labels[device]['usage'].setText(
                            f"已用 {used_gb:.1f}GB / 总计 {total_gb:.1f}GB"
                        )
                        self.disk_info_labels[device]['free'].setText(
                            f"剩余 {free_gb:.1f}GB ({100 - current_info['percent']:.1f}%)"
                        )
    def setup_monitoring(self):
        """设置监控定时器"""
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_data)
        self.timer.start(1000)

    def update_data(self):
        """更新数据"""
        try:
            # CPU 使用率
            cpu_usage = psutil.cpu_percent(interval=None)
            self.cpu_progress.setValue(cpu_usage)

            # 内存使用率
            memory = psutil.virtual_memory()
            memory_usage = memory.percent
            self.memory_progress.setValue(memory_usage)
            self.memory_total_card.update_value(f"{memory.total / (1024 ** 3):.1f}", "GB")
            self.memory_available_card.update_value(f"{memory.available / (1024 ** 3):.1f}", "GB")

            # 交换内存使用率
            swap = psutil.swap_memory()
            swap_usage = swap.percent
            self.swap_progress.setValue(swap_usage)

            # 磁盘使用率
            try:
                disk = psutil.disk_usage('C:\\')  # Windows
            except Exception:
                disk = psutil.disk_usage('/')  # Linux/macOS
            disk_usage = disk.percent
            self.disk_progress.setValue(disk_usage)

            # 网络流量
            network_io = psutil.net_io_counters()
            if self.last_network_io:
                upload_speed = (network_io.bytes_sent - self.last_network_io.bytes_sent) / 1024  # KB/s
                download_speed = (network_io.bytes_recv - self.last_network_io.bytes_recv) / 1024  # KB/s
                self.network_upload_card.update_value(f"{upload_speed:.1f}", "KB/s")
                self.network_download_card.update_value(f"{download_speed:.1f}", "KB/s")
            self.last_network_io = network_io

            # 优化磁盘信息更新
            self.update_disk_info()

            # 更新ECharts图表
            self.chart.update_data(cpu_usage, memory_usage, disk_usage, swap_usage)

        except Exception as e:
            print(f"更新数据时出错: {e}")
            InfoBar.error(
                title="数据更新失败",
                content=str(e),
                position=InfoBarPosition.TOP_RIGHT,
                duration=3000,
                parent=self
            )

    def change_refresh_rate(self):
        """更改刷新频率"""
        rates = [1000, 2000, 5000, 10000]
        self.timer.setInterval(rates[self.refresh_combo.currentIndex()])
        print(f"刷新频率已更改为: {rates[self.refresh_combo.currentIndex()] / 1000}秒")